package com.skj.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.ui.* ;

class Canvas
{
	private JavaScriptObject ctx ;				// Stands for context of Canvas
	private JavaScriptObject element ;			// Stands for DOM element
	
	public Canvas(int width, int height, Engine engine)
	{
		createCanvas(width, height,engine) ;
	}
	
	// 1
	public native void createCanvas(int width, int height, Engine engine)
	/*-{ 	
			var w = width ;
			var h = height ;
		
	  		var c = $doc.createElement('canvas') ;
            c.setAttribute("id", "canvas") ;
            
            c.setAttribute("width", w) ;
            c.setAttribute("height", h) ;
            
            $doc.body.appendChild(c) ;
	  	
	  		ctx = $doc.getElementById('canvas').getContext('2d');
            
            // WINDOW KEYBOARD EVENTS
            
            // KEYDOWN - Completed
            $wnd.onkeydown = function(event)
            {
            	var source = event.which ;
        		engine.@com.skj.client.Engine::outputPress(III)(source, -1, -1) ;
            } ;
            
            // KEYPRESS - Completed
            $wnd.onkeypress = function(event)
            {
            	// Doing same work as onkeydown but only small letter coming instead of capital
        		//var source = event.which ;
        		//engine.@com.skj.client.Engine::outputPress(III)(source, -1, -1) ;
            } ;
            
            // KEYUP - Completed
            $wnd.onkeyup = function(event)
            {
        		var source = event.which ;
        		engine.@com.skj.client.Engine::outputRelease(III)(source, -1, -1) ;
            } ;
            
            // CANVAS MOUSE EVENTS
            
            // MOUSE OVER
            c.onmouseover = function(event)
            {
        		var source = event.button ;
            	var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputEnter(III)(source, mouseX,mouseY) ;
            } ;
            
            // MOUSE OUT
            c.onmouseout = function(event)
            {
        		var source = event.button ;
            	var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputExit(III)(source, mouseX,mouseY) ;
            } ;
            
            // MOUSE DOWN - Completed
            c.onmousedown = function(event)
            {
            	var source = event.button ;
            	var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputPress(III)(source, mouseX,mouseY) ;
            } ;
            
            // MOUSE UP - Completed
            c.onmouseup = function(event)
            {
            	var source = event.button ;
        		var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputRelease(III)(source, mouseX,mouseY) ;
            } ;
            
            // ON CLICK - Completed
            c.onclick = function(event)
            {
            	var source = event.button ;
        		var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputClick(III)(source, mouseX,mouseY) ;
            } ;
            
            // ON DOUBLE CLICK - Completed
            c.ondblclick = function(event)
            {
            	var source = event.button ;
        		var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputDouble_Click(III)(source, mouseX,mouseY) ;
            } ;
            
            // MOUSE MOVE - Completed
            c.onmousemove = function(event)
            {
            	var source = event.button ;
        		var mouseX = event.clientX ;
            	var mouseY = event.clientY ;
            	
        		engine.@com.skj.client.Engine::outputMove(III)(source, mouseX,mouseY) ;
            } ;
	}-*/;
	
	// 2 - push state of canvas on state stack
	public native void save()
	/*-{  
	  		ctx.save() ;
	}-*/;
	
	// 3 - pop state stack of canvas and restore state
	public native void restore()
	/*-{  
	  		ctx.restore() ;
	}-*/;
	
	// 4 - transformations (default transform is the identity matrix)
	public native void scale(double x, double y)
	/*-{
	  		ctx.scale(x,y) ;
	}-*/;
	
	// 5 - Rotate
	public native void rotate(double angle)
	/*-{  
		ctx.rotate();
	}-*/;
	
	// 6 - Translate
	public native void translate(double x,  double y)
	/*-{  
		ctx.translate(x,y) ;
	}-*/;
	
	// 7 - Transform
	public native void transform(double m11,  double m12,  double m21,  double m22,  double dx,  double dy)
	/*-{  
		ctx.transform(m11,m12m,m21,m22,dx,dy) ;
	}-*/;
	
	// 8 - Set Transfrom
	public native void setTransform(double m11,  double m12,  double m21,  double m22,  double dx,  double dy)
	/*-{  
		ctx.setTransform(m11,m12,m21,m22,dx,dy) ;
	}-*/;
	
	// 9 - Linear Gradient
	public native void createLinearGradient(double x0,  double y0,  double x1,  double y1)
	/*-{  
		context.createLinearGradient(x0, y0, x1, y1) ;
	}-*/;
	
	// 10 - Radial Gradient
	public native void createRadialGradient(double x0,  double y0,  double r0,  double x1,  double y1,  double r1)
	/*-{  
		context.createRadialGradient(x0, y0, r0, x1, y1, r1) ;
	}-*/;
	
	// 11 - Image Pattern
	public native void createPattern(Image image,  String repetition)
	/*-{  
		context.createPattern(image, repetition) ;
	}-*/;
	
	// 12 - Clear Rectangle
	public native void clearRect(double x,  double y,  double w,  double h)
	/*-{  
		ctx.clearRect(x, y, w, h) ;
	}-*/;
	
	// 14 - Stroke Rectangle
	public native void strokeRect(double x,  double y,  double w,  double h)
	/*-{  
		ctx.strokeRect(x, y, w, h) ;
	}-*/;
	
	// 15 - Line Begin Path
	public native void beginPath()
	/*-{  
		ctx.beginPath() ;
	}-*/;
	
	// 16 - Close Path
	public native void closePath()
	/*-{  
		ctx.closePath() ;
	}-*/;
	
	// 17 - Move to
	public native void moveTo(double x,  double y)
	/*-{  
		ctx.moveTo(x, y) ;
	}-*/;
	
	// 18 - Line to
	public native void lineTo(double x,  double y)
	/*-{  
		ctx.lineTo(x, y) ;
	}-*/;
	
	// 19 - Quadratic Curve
	public native void quadraticCurveTo(double cpx,  double cpy,  double x,  double y)
	/*-{  
		ctx.quadraticCurveTo(cpx, cpy, x, y) ;
	}-*/;
	
	// 20 - Bezier Curve
	public native void bezierCurveTo(double cp1x,  double cp1y,  double cp2x,  double cp2y,  double x,  double y)
	/*-{  
		ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) ;
	}-*/;
	
	// 21 - Arc To
	public native void arcTo(double x1,  double y1,  double x2,  double y2,  double radius)
	/*-{  
		ctx.arcTo(x1, y1, x2, y2, radius) ;
	}-*/;
	
	// 22 - Rectangle
	public native void rect(double x,  double y,  double w,  double h)
	/*-{  
		ctx.rect(x, y, w, h) ;
	}-*/;
	
	// 23
	public native void arc(double x,  double y,  double radius,  double startAngle,  double endAngle,  double anticlockwise)
	/*-{
		if(anticlockwise == 0)
		{
			ctx.arc(x, y, radius, startAngle, endAngle, false) ;
		}
		else
		{
			ctx.arc(x, y, radius, startAngle, endAngle, true) ;
		}
	}-*/;
	
	// 24 - Fill
	public native void fill()
	/*-{  
		ctx.fill() ;
	}-*/;
	
	// 25 - Stroke
	public native void stroke()
	/*-{  
		ctx.stroke() ;
	}-*/;
	
	// 26
	public native void clip()
	/*-{  
		ctx.clip() ;
	}-*/;
	
	// 27
	public native void isPointInPath(double x, double y)
	/*-{  
		ctx.isPointInPath(x, y) ;
	}-*/;
	
	// 28
	public native void drawFocusRing(JavaScriptObject element,  double xCaret,  double yCaret)
	/*-{  
		shouldDraw = ctx.drawFocusRing(element, x, y, [ canDrawCustom ]) ;
	}-*/;
	
	// 29
	public native void drawFocusRing(JavaScriptObject element,  double xCaret,  double yCaret, double canDrawCustom)
	/*-{  
		
	}-*/;
	
	// 30 - Fill Text
	public native void fillText(String text,  double x,  double y)
	/*-{  
		ctx.fillText(text, x, y) ;
	}-*/;
	
	// 31 - Fill Text with Max Width
	public native void fillText(String text,  double x,  double y, double maxWidth)
	/*-{  
		ctx.fillText(text, x, y , maxWidth) ;
	}-*/;
	
	// 32 - Stroke Text
	public native void strokeText(String text,  double x,  double y)
	/*-{  
		ctx.strokeText(text, x, y ) ;
	}-*/;
	
	// 33 - Stroke Text with Max Width
	public native void strokeText(String text,  double x,  double y,  double maxWidth)
	/*-{  
		ctx.strokeText(text, x, y, maxWidth ) ;
	}-*/;
	
	// 34 - Drawing Images
	public native void drawImage(JavaScriptObject image,  double dx, double dy)
	/*-{  
		ctx.drawImage(image, dx, dy) ;
	}-*/;
	
	// 35 - Drawing Images
	public native void drawImage(JavaScriptObject image, double dx,  double dy, double dw,  double dh)
	/*-{  
			ctx.drawImage(image, dx, dy, dw, dh) ;
	}-*/;
	
	// 36 - drawing images
	public native void drawImage(JavaScriptObject image, double sx,  double sy,  double sw,  double sh,  double dx,  double dy,  double dw,  double dh)
	/*-{
			var maxW = image.width ;
			var maxH = image.height ;
			
			if(sx + sw > maxW)
			{
				sw = maxW - sx ;
			}
			
			if(sy + sh > maxH)
			{
				sh = maxH - sy ;
			}
			
			ctx.drawImage(image, sx,  sy,  sw,  sh,  dx,  dy,  dw,  dh) ;
	}-*/;
	
	// 37 - drawing images
	public native void drawImage(Canvas canvas,  double dx, double dy)
	/*-{  
		
	}-*/;
	
	// 38 - drawing Canvas
	public native void drawCanvas(Canvas canvas, double dx,  double dy)
	/*-{  
	
	}-*/;
	
	// 39 - drawing Video
	public native void drawVideo(Video video, double dx,  double dy)
	/*-{  
	
	}-*/;
	
	// 40 - drawing images
	public native void drawImage(Canvas canvas, double dx,  double dy, double dw,  double dh)
	/*-{  
	
	}-*/;
	
	// 41 - drawing images Video
	public native void drawImage(Video video, double dx,  double dy, double dw,  double dh)
	/*-{  
	
	}-*/;
	
	// 42 - drawing images
	public native void drawImage(Canvas canvas, double sx,  double sy,  double sw,  double sh,  double dx,  double dy,  double dw,  double dh)
	/*-{  
	
	}-*/;
	
	// 43 - drawing images Video
	public native void drawImage(Video video, double sx,  double sy,  double sw,  double sh,  double dx,  double dy,  double dw,  double dh)
	/*-{  
	
	}-*/;
	
	// Java Method
	public native void drawLine(double x1, double y1, double x2, double y2) 
	/*-{
		ctx.beginPath() ;
		ctx.moveTo(x1 + 0.5,y1 + 0.5) ;
		ctx.lineTo(x2 + 0.5,y2 + 0.5) ;
		ctx.closePath() ;
		ctx.stroke() ;
	}-*/;
	
	public native void drawOval(int x, int y, int width, int height)
	/*-{
		var radius = width / 2 ;
		ctx.arc(x, y, radius, 0, 360, true) ;
		ctx.stroke() ;
	}-*/;
	
	public native void drawRect(double x, double y, double width, double height, boolean color, double r, double g, double b)
	/*-{
			if(color == true)
			{
				ctx.strokeStyle = "RGB(" + r + "," + g + "," + b + ")" ;
			}
			
			ctx.strokeRect(x - 0.5, y - 0.5 , width, height) ;
	}-*/;
	
	public native void drawRoundRect(double x, double y, double width, double height, double arcWidth, double arcHeight)
	/*-{
		//ctx.rect(x, y, w, h) ;
	}-*/;
	
	public native void fillOval(double x, double y, double width, double height) 
	/*-{
		//ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise) ;
		//ctx.fill();
	}-*/;
	
	public native void fillRect(double x, double y, double width, double height, boolean color, double r, double g, double b) 
	/*-{
			if(color == true)
			{
				ctx.fillStyle = "RGB(" + r + "," + g + "," + b + ")" ;
			}
		
			ctx.fillRect(x - 0.5, y - 0.5, width, height) ;
	}-*/;
	
	public native void fillRoundRect(double x, double y, double width, double height, double arcWidth, double arcHeight)
	/*-{
		//ctx.fillStyle = "blue" ;
		//ctx.fillRect(x, y, w, h) ;
	}-*/;
	
	public native void setClip(double x, double y, double width, double height) 
	/*-{
		
	}-*/;
	
	public native void drawFrame(Image image, double xOffset, double yOffset, double x,  double y, double w,  double h)
	/*-{  
			ctx.drawImage(image, xOffset, yOffset, w, h, x, y, w, h) ;
	}-*/;
	
	public native JavaScriptObject createImage(String uri)
	/*-{  
 			var img = new Image(); 			// Create new Image object
			img.src = uri ;					// Set source path
			return img ;
	}-*/;
	
	public native JavaScriptObject createVideo(String uri)
	/*-{  
 			var video = new Image(); 		// Create new Image object
			video.src = uri ;					// Set source path
			return img ;
	}-*/;
	
	public native JavaScriptObject createAudio(String uri)
	/*-{  
 			var img = new Image(); 			// Create new Image object
			img.src = uri ;					// Set source path
			return img ;
	}-*/;
}

/* Useful Facts
+ JSNI stands for JavaScript Native Interface
+ Window can be accessed  JSNI within GWT using $wnd name
+ Document can be accessed  JSNI within GWT using $doc name
*/